package com.lagou.edu.authority.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.lagou.edu.authority.dto.AllocateRoleResourceDTO;
import com.lagou.edu.authority.entity.Resource;
import com.lagou.edu.authority.entity.RoleResource;
import com.lagou.edu.authority.mapper.ResourceMapper;
import com.lagou.edu.authority.param.ResourceQueryParam;
import com.lagou.edu.authority.service.IResourceService;
import com.lagou.edu.authority.service.IRoleResourceService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * TODO
 *
 * @author lm
 * @since 2021/11/5 11:08
 */
@Service
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements IResourceService {
    @Autowired
    IRoleResourceService roleResourceService;

    @Override
    public Page<Resource> getResourcePages(ResourceQueryParam resourceQueryParam) {
        Page<Resource> page = new Page<>(resourceQueryParam.getCurrent(), resourceQueryParam.getSize());
        return lambdaQuery()
                .eq(Objects.nonNull(resourceQueryParam.getId()), Resource::getId, resourceQueryParam.getId())
                .like(StringUtils.isNotBlank(resourceQueryParam.getName()), Resource::getName, resourceQueryParam.getName())
                .like(StringUtils.isNotBlank(resourceQueryParam.getUrl()), Resource::getUrl, resourceQueryParam.getUrl())
                .eq(Objects.nonNull(resourceQueryParam.getCategoryId()), Resource::getCategoryId, resourceQueryParam.getCategoryId())
                .ge(Objects.nonNull(resourceQueryParam.getStartCreateTime()), Resource::getCreatedTime, resourceQueryParam.getStartCreateTime())
                .le(Objects.nonNull(resourceQueryParam.getEndCreateTime()), Resource::getCreatedTime, resourceQueryParam.getEndCreateTime())
                .orderByDesc(Resource::getId)
                .page(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean allocateRoleResources(AllocateRoleResourceDTO allocateRoleResourceDTO) {
        if (CollectionUtils.isEmpty(allocateRoleResourceDTO.getResourceIdList())) {
            // 表示删除所有角色资源
            allocateRoleResourceDTO.setResourceIdList(Lists.newArrayList());
        }
        // 已分配的资源ID列表
        Set<Integer> roleResourceIds = roleResourceService.queryResourceByRoleId(allocateRoleResourceDTO.getRoleId());
        // 当前准备分配的资源ID列表
        Set<Integer> allocateRoleResourceIds = Sets.newHashSet(allocateRoleResourceDTO.getResourceIdList());

        // 本次要删除的角色-资源关系
        Set<Integer> needToDel = roleResourceIds.stream().filter(resourceId -> !allocateRoleResourceIds.contains(resourceId)).collect(Collectors.toSet());
        // 本次要新增的角色-资源关系
        Set<Integer> needToInsert = allocateRoleResourceIds.stream().filter(resourceId -> !roleResourceIds.contains(resourceId)).collect(Collectors.toSet());

        if (!CollectionUtils.isEmpty(needToDel)) {
            roleResourceService.removeResourceByRoleIdAndResourceIds(allocateRoleResourceDTO.getRoleId(), needToDel);
        }

        if (!CollectionUtils.isEmpty(needToInsert)) {
            List<RoleResource> roleResources = needToInsert.stream().map(resourceId -> {
                RoleResource roleResource = new RoleResource();
                roleResource.setRoleId(allocateRoleResourceDTO.getRoleId());
                roleResource.setResourceId(resourceId);
                roleResource.setCreatedBy(allocateRoleResourceDTO.getCreatedBy());
                roleResource.setUpdatedBy(allocateRoleResourceDTO.getUpdatedBy());
                roleResource.setCreatedTime(new Date());
                roleResource.setUpdatedTime(new Date());
                return roleResource;
            }).collect(Collectors.toList());
            return roleResourceService.saveBatch(roleResources);
        }
        return Boolean.TRUE;
    }
}
